package netty.test9nettySimple;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        //1,创建 bossGroup 和workerGroup
        //创建了两个线程组 bossGroup 和workerGroup,
        //bossGroup 处理连接请求， 业务处理 交给 workerGroup 完成，这两个group 都是无限循环
        // bossGroup 和workerGroup 含有的子线程的个数（NioEventLoop)默认值是 cpu核数*2
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);
        try {
            //2,创建服务器端启动对象，可以去配置启动参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            //3,设置启动参数

            serverBootstrap
                    .group(bossGroup, workerGroup)//设置两个线程组
                    .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel 作为服务器的通道实现
                    .option(ChannelOption.SO_BACKLOG, 128)//设置线程队列等待连接的个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true)//设置保持活动连接状态
                    //.handler(null)//hanler 对应的是 bossGroup , childHandler对应的是 workerGroup
                    .childHandler(new ChannelInitializer<SocketChannel>() {//给我们的workerGroup的EventLoop的对应的管道设置处理器

                        @Override
                        public void initChannel(SocketChannel socketChannel) throws Exception {
                            System.out.println("客户socketChannel hashcode=" + socketChannel.hashCode());
                            socketChannel.pipeline().addLast(new ServerHandler1());//handler(netty 提供了很多handler,也可以自己提供handler)
                        }
                    });

            System.out.println("server is reading......");
            //1,绑定一个端口，并且同步，生成一个 ChannelFuture 对象()(这个地方相当于 启动服务器，并监听端口)
            final ChannelFuture cf = serverBootstrap.bind(6668).sync();
            //给  channelFuture  注册监听器，监控我们关心的事件
            cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (cf.isSuccess()) {
                        System.out.println("监听端口成功");
                    } else {
                        System.out.println("监听端口失败");
                    }
                }
            });


            //2,对关闭通道进行监听（这个地方不是关闭，只是对关闭进行监听）(这个地方回阻塞，
            // 不会走到下面的finally，除非上面的出现一次)
            System.out.println("closeFuture start........");
            cf.channel().closeFuture().sync();
            System.out.println("closeFuture end........");
        } finally {
            System.out.println("--关闭------------------");
            //优雅的关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
